from py2neo import Graph, Node, Relationship
import pandas as pd
import time

# -------------------------- 配置你的Neo4j数据库连接 --------------------------
# 请替换为你的实际连接信息
NEO4J_URI = "bolt://localhost:7687"
NEO4J_USER = "neo4j"
NEO4J_PASSWORD = "053116wj"


def run_reasoning():
    """
    执行知识图谱推理的完整流程
    """
    try:
        graph = Graph(NEO4J_URI, auth=(NEO4J_USER, NEO4J_PASSWORD))
        print("✅ 成功连接到 Neo4j 数据库。")

    except Exception as e:
        print(f"❌ 连接 Neo4j 失败：{str(e)}")
        return

    # -------------------------- 1. 基于规则的推理：创建共享属性关系 --------------------------
    print("\n--- 步骤 1: 基于规则的推理，创建共享属性关系 ---")
    start_time = time.time()

    # Cypher 查询列表，用于创建不同类型的共享属性关系
    queries = [
        ("余味", "致甜成分余味余味"),
        ("持久性", "致甜成分甜味持久性"),
        ("相对甜度", "致甜成分相对甜度"),
        ("特点", "致甜成分特点"),
        ("应用", "致甜成分应用")
        # 如果有其他想分析的属性，可以在这里继续添加
    ]

    for rel_type, node_label in queries:
        query = f"""
        MATCH (s1:致甜成分)-[:{rel_type}]->(p:{node_label})<-[:{rel_type}]-(s2:致甜成分)
        WHERE id(s1) <> id(s2) AND NOT EXISTS((s1)-[:共同属性 {{type: '{rel_type}'}}]-(s2))
        MERGE (s1)-[:共同属性 {{type: '{rel_type}'}}]->(s2)
        """
        result = graph.run(query).to_data_frame()
        print(f"  • 创建基于 '{rel_type}' 的共享关系...")

    print(f"✅ 共享属性关系创建完成。耗时: {time.time() - start_time:.2f}秒")

    # -------------------------- 2. 基于图算法的推理：运行社区检测 --------------------------
    print("\n--- 步骤 2: 基于图算法的推理，运行 Louvain 社区检测 ---")

    # GDS 要求先创建内存图投影
    gds_start_time = time.time()
    try:
        projection_query = """
        CALL gds.graph.project(
            'sweetener_network',
            ['致甜成分名称'],
            {
                共同属性: {
                    type: '共同属性',
                    orientation: 'UNDIRECTED'
                }
            }
        )
        YIELD graphName, nodeCount, relationshipCount
        """
        result = graph.run(projection_query).data()
        print(f"  • 成功创建图投影 '{result[0]['graphName']}'")
        print(f"    - 包含节点数: {result[0]['nodeCount']}，关系数: {result[0]['relationshipCount']}")

        # 运行 Louvain 算法
        louvain_query = """
        CALL gds.louvain.write(
          'sweetener_network',
          {
            writeProperty: 'communityId'
          }
        )
        YIELD nodeCount, communityCount, ranIterations
        """
        louvain_result = graph.run(louvain_query).data()
        print(f"  • Louvain 算法运行完成。发现 {louvain_result[0]['communityCount']} 个社区。")

    except Exception as e:
        print(f"❌ 运行 GDS 算法失败，请检查 Neo4j GDS 插件是否已安装和启用：{str(e)}")
        return

    print(f"✅ Louvain 社区检测完成。耗时: {time.time() - gds_start_time:.2f}秒")

    # -------------------------- 3. 结果提取与分析 --------------------------
    print("\n--- 步骤 3: 提取并分析推理结果 ---")

    # 提取 Louvain 社区检测结果
    results_query = """
    MATCH (s:致甜成分名称)
    RETURN s.name AS sweetenerName, s.communityId AS communityID
    ORDER BY communityID, sweetenerName
    """
    results_df = graph.run(results_query).to_data_frame()

    if results_df.empty:
        print("无结果，请检查知识图谱中是否有足够的致甜成分节点和关系。")
        return

    print("📊 社区检测结果（部分）：")
    print(results_df.head())

    # 按社区ID分组，打印每个社区的成员
    community_groups = results_df.groupby('communityID')['sweetenerName'].apply(list)
    print("\n📦 按社区分组的致甜成分：")
    for community_id, members in community_groups.items():
        print(f"  • 社区ID {community_id} (成员数量: {len(members)}):")
        print("    " + ", ".join(members))

    print("\n🎉 所有推理步骤已完成！你可以通过分析这些社区成员，来寻找它们之间潜在的协同或抑制关系。")


if __name__ == "__main__":
    run_reasoning()